package com.base.springboot.starter.common.http;

import java.util.concurrent.TimeUnit;

/**
 * Description:
 * User: wangwei
 * Date: 2021-05-27 4:42 下午
 */
public class CsHttpClientConfig {

    private int maxConnPerRoute;
    private int maxConnTotal;
    private String preheatUrl;
    private int maxPreheatConn;
    private long connTimeToLive;
    private boolean closeIdleConnections;
    private int validateAfterInactivityInMs;


    private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS;

    public CsHttpClientConfig(Builder builder) {
        this.maxConnPerRoute = builder.maxConnPerRoute;
        this.maxConnTotal = builder.maxConnTotal;
        this.preheatUrl = builder.preheatUrl;
        this.maxPreheatConn = builder.maxPreheatConn;
        this.connTimeToLive = builder.connTimeToLive;
        this.closeIdleConnections = builder.closeIdleConnections;
        this.validateAfterInactivityInMs = builder.validateAfterInactivityInMs;
    }

    public int getMaxConnPerRoute() {
        return maxConnPerRoute;
    }

    public int getMaxConnTotal() {
        return maxConnTotal;
    }

    public String getPreheatUrl() {
        return preheatUrl;
    }

    public int getMaxPreheatConn() {
        return maxPreheatConn;
    }

    public long getConnTimeToLive() {
        return connTimeToLive;
    }

    public TimeUnit getConnTimeToLiveTimeUnit() {
        return connTimeToLiveTimeUnit;
    }

    public boolean isCloseIdleConnections() {
        return closeIdleConnections;
    }

    public int getValidateAfterInactivityInMs() {
        return validateAfterInactivityInMs;
    }

    public static class Builder{

        private static final int DEFAULT_MAX_TOTAL = 50;
        private static final int MAX_TOTAL = 200;
        private static final int DEFAULT_MAX_PER_ROUTE = 50;

        private static final int DEFAULT_MAX_PRE_HEAT = 10;
        private static final int MAX_PRE_HEAT = 20;

        private static final int DEFAULT_TIME_TO_LIVE = -1;

        /** 总最大并发数 */
        private int maxConnTotal = DEFAULT_MAX_TOTAL;

        /** 每host最大并发数 见 AbstractConnPool 351-384 行*/
        private int maxConnPerRoute = DEFAULT_MAX_PER_ROUTE;

        /** 预热url */
        private String preheatUrl;

        /** 预热连接数 */
        private int maxPreheatConn = DEFAULT_MAX_PRE_HEAT;

        /** 存活时间 见 PoolEntry 87行 */
        private long connTimeToLive = DEFAULT_TIME_TO_LIVE;

        /** 关闭空闲连接 */
        private boolean closeIdleConnections = false;

        /** 获取连接时是否检查不活跃时长超过N(ms)的连接，不设置默认2s，见 PoolingHttpClientConnectionManager 183行 */
        private int validateAfterInactivityInMs;

        public CsHttpClientConfig build() {
            if (maxConnTotal > MAX_TOTAL) {
                throw new IllegalArgumentException("最大连接数不要超过 " + MAX_TOTAL);
            }
            if (maxPreheatConn > MAX_PRE_HEAT) {
                throw new IllegalArgumentException("预热连接数不要超过 " + MAX_PRE_HEAT);
            }
            if (maxConnPerRoute > maxConnTotal) {
                maxConnPerRoute = maxConnTotal;
            }
            return new CsHttpClientConfig(this);
        }

        /**
         *  注意：由于直接写根域名可能会被对方防火墙封杀，所以这里要写具体的接口
         * @param preheatUrl
         * @return
         */
        public Builder setPreheatUrl(String preheatUrl){
            //TODO 检查根域
            this.preheatUrl = preheatUrl;
            return this;
        }

        public Builder setMaxConnTotal(int maxConnTotal){
            this.maxConnTotal = maxConnTotal;
            return this;
        }

        public Builder setMaxConnPerRoute(int maxConnPerRoute){
            this.maxConnPerRoute = maxConnPerRoute;
            return this;
        }

        public Builder setConnTimeToLiveInMilliSec(int connTimeToLiveInMilliSec){
            this.connTimeToLive = connTimeToLiveInMilliSec;
            return this;
        }

        public Builder setCloseIdleConnections(boolean closeIdleConnections){
            this.closeIdleConnections = closeIdleConnections;
            return this;
        }

        public Builder setValidateAfterInactivityInMs(int validateAfterInactivityInMs){
            this.validateAfterInactivityInMs = validateAfterInactivityInMs;
            return this;
        }

        public Builder setMaxPreheatConn(int maxPreheatConn){
            this.maxPreheatConn = maxPreheatConn;
            return this;
        }

    }

    @Override
    public String toString() {
        return "CsHttpClientConfig{" +
                "maxConnPerRoute=" + maxConnPerRoute +
                ", maxConnTotal=" + maxConnTotal +
                ", preheatUrl='" + preheatUrl + '\'' +
                ", maxPreheatConn=" + maxPreheatConn +
                ", connTimeToLive=" + connTimeToLive +
                ", closeIdleConnections=" + closeIdleConnections +
                ", validateAfterInactivityInMs=" + validateAfterInactivityInMs +
                ", connTimeToLiveTimeUnit=" + connTimeToLiveTimeUnit +
                '}';
    }
}
